/*
Copyright 2002-2003 The University of Texas at Austin

Authors: Anthony Thane <thanea@ices.utexas.edu>
Vinay Siddavanahalli <skvinay@cs.utexas.edu>
Advisor: Chandrajit Bajaj <bajaj@cs.utexas.edu>

This file is part of Volume Rover.

Volume Rover is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

Volume Rover is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with iotree; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
#include <assert.h>
#include <QFile>
#include <QtAlgorithms>
#include "alphamap.h"

using namespace PBVP;

AlphaMap::AlphaMap()
{
	m_AlphaNodes.append(AlphaMapNode(0.0, 0.0));
	m_AlphaNodes.append(AlphaMapNode(1.0, 1.0));
	AddNode(0.25, 0.75);
	AddNode(0.75, 0.25);
}

AlphaMap::AlphaMap(const AlphaMap& copy)
{
	m_AlphaNodes = copy.m_AlphaNodes;
}

AlphaMap AlphaMap::operator=(const AlphaMap& copy)
{
	if (this == &copy)
	{
		return *this;
	}
	m_AlphaNodes = copy.m_AlphaNodes;
	return *this;
}

void AlphaMap::AddNode(double pos, double alpha)
{
	assert(pos>=0.0 && pos<=1.0);
	m_AlphaNodes.append(AlphaMapNode(pos, alpha));
	qSort(m_AlphaNodes);
}

void AlphaMap::AddNode(double pos)
{
	assert (pos>=0.0 && pos<=1.0);
	double alpha = GetAlpha(pos);
	m_AlphaNodes.append(AlphaMapNode(pos, alpha));
	qSort(m_AlphaNodes);
}

void AlphaMap::DeleteNode(int index)
{
	if (index < size()-1 && index > 0)
	{
		m_AlphaNodes.removeAt(index);
	}
}

void AlphaMap::MoveNode(int index, double pos)
{
	if (index < size()-1 && index > 0)
	{
		m_AlphaNodes[index].position = pos;
		qSort(m_AlphaNodes);
	}
}

int AlphaMap::size() const
{
	return m_AlphaNodes.size();
}

double AlphaMap::GetPosition(int index) const
{
	return m_AlphaNodes[index].position;
}

double AlphaMap::GetAlpha(int index) const
{
	return m_AlphaNodes[index].alpha;
}

void AlphaMap::ChangeAlpha(int index, double alpha)
{
	if(alpha > 1.0) alpha = 1.0;
	if(alpha < 0) alpha = 0;
	m_AlphaNodes[index].alpha = alpha;
}

double AlphaMap::GetAlpha(double pos) const
{
	assert(pos>=0.0 && pos<=1.0);

	QList<AlphaMapNode>::const_iterator i = m_AlphaNodes.begin();
	while ( i->position < pos)
	{
		++i;
	}
	if (i == m_AlphaNodes.begin())
	{  // pos at the first Alpha Node 
		return i->alpha;
	} else
	{
		double alpha2 = i->alpha;
		double p2 = i->position;
		--i;
		double alpha1 = i->alpha;
		double p1 = i->position;

		if (p1 == p2) return alpha1;
		double alpha = (alpha1*(p2-pos) + alpha2*(pos-p1))/(p2-p1);
		return alpha;
	}
}

/********************

Alphamap
No of nodes
< no of nodes >
Position and opacity
< Position A1 >
< Position AN >
< Position A2 >
< Position A3 >
...
< Position AN-1 >

*********************/
void AlphaMap::saveMap( QTextStream& stream )
{
	stream << "Alphamap\n";
	stream << "Number of nodes\n";
	stream << size() << "\n";

	stream << "Position and opacity\n";

	for ( int i = 0; i < size(); i++ )
	{
		stream << m_AlphaNodes[i].position << " "  << m_AlphaNodes[i].alpha << "\n";
	}
}

void AlphaMap::loadMap( QTextStream& stream )
{
	double position, alpha;
	int size;
	QString junk;

	m_AlphaNodes.clear();

	stream.skipWhiteSpace();
	junk = stream.readLine(); // Alphamap

	stream.skipWhiteSpace();
	junk = stream.readLine(); // Number of nodes
	stream >> size;

	stream.skipWhiteSpace(); // end of size line
	junk = stream.readLine(); // Position and opacity

	for ( int i=0; i < size; i++ )
	{
		stream >> position >> alpha;
		m_AlphaNodes.append(AlphaMapNode(position, alpha));
	}
	qSort(m_AlphaNodes);
}

void AlphaMap::removeSandwichedNodes(){
	// when there are 3 or more nodes with the same position
	// remove the ones in the middle

	if (size() < 3)
	{ // with size < 3, cant have sandwiched nodes
		return;
	}

	int i = 1;
	while(i < size()-1)
	{
		AlphaMapNode prev = m_AlphaNodes[i-1];
		AlphaMapNode next = m_AlphaNodes[i+1];
		AlphaMapNode curr = m_AlphaNodes[i];
		if(curr.position == prev.position && curr.position == next.position)
		{
			m_AlphaNodes.removeAt(i);
		} else {
			i++;
		}
	}
}


